package com.temi.iot.config.shiro;

import com.temi.iot.kit.StrKit;
import org.apache.http.HttpStatus;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.AuthenticatingFilter;
import org.apache.shiro.web.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class JwtAuthFilter extends AuthenticatingFilter {
	private final Logger log = LoggerFactory.getLogger(JwtAuthFilter.class);
	
    private static final int tokenRefreshInterval = 300;
   // private TokenInterface tokenInterface = null;

    public JwtAuthFilter(){

        //this.setLoginUrl("/swagger-ui.html");
    }

    /**
     * 拦截器 -所有请求均通过此方法
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @Override
    protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
        HttpServletRequest httpServletRequest = WebUtils.toHttp(request);
        //对于OPTION请求做拦截，不做token校验
        if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {
            return false;
        }


        return super.preHandle(request, response);
    }

    /**
     * 请求调用结束时调用
     * @param request
     * @param response
     */
    @Override
    protected void postHandle(ServletRequest request, ServletResponse response){
        request.setAttribute("jwtShiroFilter.FILTERED", true);
    }

    /**
     * 是否运行通过
     * @param request
     * @param response
     * @param mappedValue
     * @return true-通行 ,false-不通行
     */
    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
        //判断当前路径是否为拦截路径
        if( this.isLoginRequest(request, response)){
            return true;
        }
        boolean allowed = false;
        try {
            allowed = executeLogin(request, response);
        } catch(IllegalStateException e){
            log.error("Not found any token");
        }catch (Exception e) {
            log.error("Error occurs when login", e);
        }
        return allowed || super.isPermissive(mappedValue);
    }

    /**
     *  调用executeLogin(requet,response)时调用此方法来创建本次校验Token
     *
     *  executeLogin()源码：AuthenticationToken token = this.createToken(request, response);
     * @param servletRequest
     * @param servletResponse
     * @return
     */
    @Override
    protected AuthenticationToken createToken(ServletRequest servletRequest, ServletResponse servletResponse) {
        String jwtToken = getAuthzHeader(servletRequest);
        if(jwtToken !=null && !"".equals(jwtToken)){
            return new JWTToken(jwtToken);
        }
        return null;
    }

    /**
     * 拒绝通行
     * @param servletRequest
     * @param servletResponse
     * @return
     * @throws Exception
     */
    @Override
    protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {
        HttpServletResponse httpResponse = WebUtils.toHttp(servletResponse);
        httpResponse.setCharacterEncoding("UTF-8");
        httpResponse.setContentType("application/json;charset=UTF-8");
        httpResponse.setStatus(HttpStatus.SC_NON_AUTHORITATIVE_INFORMATION);
        return false;
    }

    /**
     * 同意通行
     * 同意通行后将token解析
     * @param token
     * @param subject
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @Override
    protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response) throws Exception {
        if(token instanceof JWTToken){
            JWTToken jwtToken = (JWTToken)token;

        }
        return true;
    }

    @Override
    protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e, ServletRequest request, ServletResponse response) {
        log.info("Validate token fail, token:{}, error:{}", token.toString(), e.getMessage());
        return false;
    }

    /**
     * 工具类获取Header中token字段
     * @param request
     * @return
     */
    protected String getAuthzHeader(ServletRequest request) {
        HttpServletRequest httpRequest = WebUtils.toHttp(request);
        String token = httpRequest.getHeader("Authorization");
        if (StrKit.isEmpty(token)) {
            token = request.getParameter("Authorization");
        }
        return token;
    }
}
